package com.ikas.ai.server.module.assessment.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ikas.ai.enums.redis.RedisKeyEnum;
import com.ikas.ai.server.error.BusinessException;
import com.ikas.ai.server.module.AssessModelTaskService;
import com.ikas.ai.server.module.appraise.enums.AssessStatusEnum;
import com.ikas.ai.server.module.appraise.enums.StatusEnum;
import com.ikas.ai.server.module.assessment.dao.AssessModelMapper;
import com.ikas.ai.server.module.assessment.enums.TriggerFromEnum;
import com.ikas.ai.server.module.assessment.model.dto.AmTriggerDto;
import com.ikas.ai.server.module.assessment.model.po.AssessModel;
import com.ikas.ai.server.module.assessment.model.po.AssessWfResult;
import com.ikas.ai.server.module.condition.model.WorkConditionFlow;
import com.ikas.ai.server.module.condition.service.WorkConditionFlowService;
import com.ikas.ai.server.module.instance.model.DorisWorkFlowInstance;
import com.ikas.ai.server.module.instance.model.DorisWorkInstanceStepDetail;
import com.ikas.ai.server.module.instance.service.DorisWorkFlowInstanceService;
import com.ikas.ai.utils.RedisUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.CompletableFuture;

/**
 * <p>
 * 工况模型评价表 服务实现类
 * </p>
 *
 * @author wuyf
 * @since 2023-10-26
 */
@Slf4j
@Service
public class AssessModelService extends ServiceImpl<AssessModelMapper, AssessModel> {

    @Resource
    private AssessWfResultService assessWfResultService;

    @Resource
    private AssessModelTaskService assessModelTaskService;

    @Resource
    private DorisWorkFlowInstanceService dorisWorkFlowInstanceService;

    @Resource
    private WorkConditionFlowService workConditionFlowService;

    public void wakeAssessByInstanceDetail(DorisWorkInstanceStepDetail detail) {
        DorisWorkFlowInstance workFlowInstance = dorisWorkFlowInstanceService.getById(detail.getWfInstanceId());
        WorkConditionFlow workConditionFlow = workConditionFlowService.getById(detail.getWfId());
        AmTriggerDto amTriggerDto = new AmTriggerDto().setWfDesc(workConditionFlow.getWfDesc())
                .setBatch(workFlowInstance.getBatch())
                .setStepName(detail.getStepName())
                .setWfName(workConditionFlow.getWfName())
                .setWfDesc(workConditionFlow.getWfDesc())
                .setMeteCode(detail.getMeteCode())
                .setMachineNo(workFlowInstance.getMachineNo())
                //来源：工况转换
                .setTriggerFrom(TriggerFromEnum.WORK_FLOW_TRANS.getValue());

        try {
            triggerModel(amTriggerDto);
        } catch (Exception e) {
            log.error("lltrigger assess model error:{}", e.getMessage());
        }
    }


    public boolean triggerModel(AmTriggerDto triggerDto) {
        Assert.notBlank(triggerDto.getMachineNo(), "机组编号不能为空");
        Assert.notBlank(triggerDto.getMeteCode(), "测点编号不能为空");
        //尝试先从缓存获取评价模型信息
        AssessModel am = RedisUtils.selectFromCacheOrDb(
                RedisKeyEnum.ASSESS_MODEL_TRIGGER_KEY.key(triggerDto.getMachineNo(), triggerDto.getMeteCode(), 1),
                () -> getAmByMeteCode(triggerDto.getMachineNo(), triggerDto.getMeteCode(), 1)
        );
        if (am == null) {
            throw new BusinessException(String.format("未找到可用的评价模型,machineNo:【%s】,meteCode:【%s】", triggerDto.getMachineNo(), triggerDto.getMeteCode()));
        }
        if (!StatusEnum.VALID.getCode().equals(am.getStatus())) {
            throw new BusinessException("当前触发的模型还未生效");
        }
        //异步调用
        CompletableFuture.supplyAsync(() ->
                //1.保存最开始的评价结果
                saveStartOfAssessWfResult(triggerDto, am)
        ).thenAccept(assessWfResults ->
                //2.开启评价模型流程
                assessModelTaskService.execModelFlow(assessWfResults)
        );
        return true;
    }

    /**
     * 获取一条评价模型-通过meteCode
     *
     * @param machineNo   机组编号
     * @param meteCode    测点编号
     * @param triggerType 触发类型
     * @return AssessModel
     */
    private AssessModel getAmByMeteCode(String machineNo, String meteCode, int triggerType) {
        LambdaQueryWrapper<AssessModel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AssessModel::getMachineNo, machineNo);
        queryWrapper.eq(AssessModel::getMeteCode, meteCode);
        queryWrapper.eq(AssessModel::getTriggerType, triggerType);
        return this.getOne(queryWrapper);
    }


    /**
     * 保存最开始的评价结果
     *
     * @param triggerDto dto参数对象
     * @param am         模型
     */
    @SneakyThrows
    private AssessWfResult saveStartOfAssessWfResult(AmTriggerDto triggerDto, AssessModel am) {
        log.info("保存评价结果");
        AssessWfResult awfResult = BeanUtil.copyProperties(triggerDto, AssessWfResult.class);
        awfResult.setModelId(am.getId());
        awfResult.setModelName(am.getName());
        awfResult.setStatus(AssessStatusEnum.NOT_START.getStatus());
        awfResult.setMeteName(am.getMeteName());
        awfResult.setCreateTime(new Date());
        awfResult.setUpdateTime(new Date());
        assessWfResultService.save(awfResult);
        return awfResult;
    }

}
